<template>
  <div class="home">
    <div class="left" id="blocklyArea">
      <div id="blocklyDiv" style="position: absolute"></div>
    </div>
    <a-divider direction="vertical" :margin="0" />
    <div class="right">
      <div class="scence"></div>
      <div class="codeArea">
        <a-card :style="{ width: '100%', height: '100%' }" title="实时js代码">
          <template #extra>
            <a-button type="primary" @click.stop.prevent="executeCode()" style="margin-right: 10px;">运行</a-button>
          </template>
          <MdPreview :editorId="id" :modelValue="'```' + '\n' + currentCode" />
          <MdCatalog :editorId="id" :scrollElement="scrollElement" />
        </a-card>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import axios from 'axios';
import Blockly from 'blockly'
import { javascriptGenerator } from 'blockly/javascript'
// import { pythonGenerator } from 'blockly/python'
import '@blockly/toolbox-search'
import * as zh from 'blockly/msg/zh-hans';
// import * as en from 'blockly/msg/en';
import { onMounted, ref, reactive } from 'vue'
//引入markdown编辑器
import { MdPreview, MdCatalog } from 'md-editor-v3';
import 'md-editor-v3/lib/preview.css';
// 引入通知
import { Notification } from '@arco-design/web-vue';
const id = 'preview-only';
// const text = ref('# Hello Editor');
const scrollElement = document.documentElement;

let toolbox = reactive({

  "kind": "categoryToolbox",
  "contents": [
    {
      'kind': 'search',
      'name': 'Search',
      'contents': [],
    },
    {
      "kind": "category",
      "name": "逻辑",
      "colour": 210,
      "contents": [
        {
          "kind": "block",
          "type": "controls_if"
        },
        {
          "kind": "block",
          "type": "controls_ifelse"
        },
        {
          "kind": "block",
          "type": "logic_compare"
        },
        {
          "kind": "block",
          "type": "logic_boolean"
        },
        {
          "kind": "block",
          "type": "logic_null"
        },
        {
          "kind": "block",
          "type": "logic_operation"
        },
        {
          "kind": "block",
          "type": "logic_negate"
        }
      ]
    },
    {
      "kind": "category",
      "name": "循环",
      "colour": 230,
      "contents": [
        {
          "kind": "block",
          "type": "controls_repeat"
        },
        {
          "kind": "block",
          "type": "controls_repeat_ext"
        },
        {
          "kind": "block",
          "type": "controls_whileUntil"
        },
        {
          "kind": "block",
          "type": "controls_for"
        },
        {
          "kind": "block",
          "type": "controls_forEach"
        },
        {
          "kind": "block",
          "type": "controls_flow_statements"
        }
      ]
    },
    {
      "kind": "category",
      "name": "数学",
      "colour": 160,
      "contents": [
        {
          "kind": "block",
          "type": "math_number"
        },
        {
          "kind": "block",
          "type": "math_arithmetic"
        },
        {
          "kind": "block",
          "type": "math_single"
        },
        {
          "kind": "block",
          "type": "math_trig"
        },
        {
          "kind": "block",
          "type": "math_constant"
        },
        {
          "kind": "block",
          "type": "math_number_property"
        },
        {
          "kind": "block",
          "type": "math_round"
        },
        {
          "kind": "block",
          "type": "math_on_list"
        },
        {
          "kind": "block",
          "type": "math_modulo"
        },
        {
          "kind": "block",
          "type": "math_constrain"
        },
        {
          "kind": "block",
          "type": "math_random_int"
        },
        {
          "kind": "block",
          "type": "math_random_float"
        },
        {
          "kind": "block",
          "type": "math_atan2"
        }
      ]
    },
    {
      "kind": "category",
      "name": "文本",
      "colour": 120,
      "contents": [
        {
          "kind": "block",
          "type": "text"
        },
        {
          "kind": "block",
          "type": "text_join"
        },
        {
          "kind": "block",
          "type": "text_append"
        },
        {
          "kind": "block",
          "type": "text_length"
        },
        {
          "kind": "block",
          "type": "text_isEmpty"
        }
      ]
    },
    {
      "kind": "category",
      "name": "列表",
      "colour": 260,
      "contents": [
        {
          "kind": "block",
          "type": "lists_create_with"
        },
        {
          "kind": "block",
          "type": "lists_create_empty"
        },
        {
          "kind": "block",
          "type": "lists_length"
        },
        {
          "kind": "block",
          "type": "lists_isEmpty"
        },
        // {
        //   "kind": "block",
        //   "type": "lists_indexOf"
        // },
        // {
        //   "kind": "block",
        //   "type": "lists_get_index"
        // },
        // {
        //   "kind": "block",
        //   "type": "lists_set_index"
        // },
        // {
        //   "kind": "block",
        //   "type": "lists_remove_index"
        // },
        // {
        //   "kind": "block",
        //   "type": "lists_repeat"
        // },
        // {
        //   "kind": "block",
        //   "type": "lists_reverse"
        // },
        // {
        //   "kind": "block",
        //   "type": "lists_sort"
        // },
        // {
        //   "kind": "block",
        //   "type": "lists_split"
        // },
        // {
        //   "kind": "block",
        //   "type": "lists_join"
        // }
      ]
    },
    {
      "kind": "category",
      "name": "变量",
      "colour": 330,
      "contents": [
        {
          "kind": "block",
          "type": "variables_get"
        },
        {
          "kind": "block",
          "type": "variables_set"
        },
        {
          "kind": "block",
          "type": "logic_boolean"
        },
        {
          "kind": "block",
          "type": "math_number",
          "fields": {
            "NUM": 0
          }
        },
      ]
    },
    {
      "kind": "category",
      "name": "函数",
      "colour": 290,
      "contents": [
        {
          "kind": "block",
          "type": "procedures_defnoreturn"
        },
        {
          "kind": "block",
          "type": "procedures_callnoreturn"
        },
        {
          "kind": "block",
          "type": "procedures_defreturn"
        },
        {
          "kind": "block",
          "type": "procedures_callreturn"
        }
      ]
    },
    {
      "kind": "category",
      "name": "机械臂操作",
      "contents": [
        {
          "kind": "block",
          "type": "arm_move"
        },
        {
          "kind": "block",
          "type": "arm_init"
        },
        {
          "kind": "block",
          "type": "arm_grab"
        },
        {
          "kind": "block",
          "type": "arm_put"
        }
      ]
    }
  ]

})
//设置等待时间，防止代码执行过快，机械臂反应不过来
let waitTime = ref(0)
let blocklyWorkspace = ref()
let currentCode = ref('')
function updateCode() {
  currentCode.value = javascriptGenerator.workspaceToCode(blocklyWorkspace.value);
}
const Command = reactive({
  execute: (cmd: string) => {
    waitTime.value += 3000
    setTimeout(() => {
      axios.get('/api/executeCode', {
        params: {
          code: cmd
        }
      }).then(function (res) {
        console.log(res.data.data);
        Notification.success(
          res.data.data + ' 执行成功!'
        )
      })
    }, waitTime.value)

    // .catch(function (error) {
    //   console.log(error);
    // })
    // .finally(function () {
    //   // always executed
    // });
  }
})
function executeCode() {
  waitTime.value = 0
  Notification.info(
    '开始向服务器发送执行命令!'
  )
  eval(currentCode.value)
}
onMounted(() => {
  Blockly.setLocale(zh);

  //注册自定义block：arm_move
  Blockly.Blocks['arm_move'] = {
    init: function () {
      this.appendStatementInput("arm_move")
        .setCheck("String")
        .appendField(new Blockly.FieldTextInput("移动机械臂"), "arm_move");
      this.appendValueInput("DIRECTION")
        .setCheck("String")
        .appendField(new Blockly.FieldDropdown([
          ["前", "fw"],
          ["后", "bw"],
          ["左", "lf"],
          ["右", "rg"],
          ["上", "up"],
          ["下", "dw"]
        ]), 'DIRECTION');
      this.appendValueInput("steps")
        .setCheck("Number")
        .appendField(new Blockly.FieldNumber(1, 1, 6), "steps");
      this.setPreviousStatement(true, "Boolean");
      this.setNextStatement(true, "Boolean");
      this.setColour(290);
      this.setOutput(true, "Action");
      this.setTooltip("执行机械臂移动指令");
      this.setHelpUrl("");
    },
  };

  Blockly.Blocks['arm_init'] = {
    init: function () {
      this.appendStatementInput("arm_init")
        .setCheck("String")
        .appendField(new Blockly.FieldTextInput("初始化机械臂"), "arm_init");
      this.setPreviousStatement(true, "Boolean");
      this.setNextStatement(true, "Boolean");
      this.setColour(160);
      this.setTooltip("初始化机械臂");
      this.setHelpUrl("初始化机械臂");
    }
  };

  Blockly.Blocks['arm_grab'] = {
    init: function () {
      this.appendStatementInput("arm_grab")
        .setCheck("String")
        .appendField(new Blockly.FieldTextInput("机械臂抓取物品"), "arm_grab");
      this.setPreviousStatement(true, "Boolean");
      this.setNextStatement(true, "Boolean");
      this.setColour(160);
      this.setTooltip("机械臂抓取物品");
      this.setHelpUrl("机械臂抓取物品");
    }
  };

  Blockly.Blocks['arm_put'] = {
    init: function () {
      this.appendStatementInput("arm_put")
        .setCheck("String")
        .appendField(new Blockly.FieldTextInput("机械臂放下物品"), "arm_put");
      this.setPreviousStatement(true, "Boolean");
      this.setNextStatement(true, "Boolean");
      this.setColour(160);
      this.setTooltip("机械臂放下物品");
      this.setHelpUrl("机械臂放下物品");
    }
  };
  //代码生成
  javascriptGenerator.forBlock['arm_move'] = function (block: { getFieldValue: (arg0: string) => any; }) {
    const direction = block.getFieldValue("DIRECTION");
    const steps = block.getFieldValue("steps");
    return '\n' + `Command.execute('./armMove -${direction} ${steps}')`;
  }

  javascriptGenerator.forBlock['arm_init'] = function (block: { getFieldValue: (arg0: string) => any; }) {
    return '\n' + `Command.execute('./armMove -init')`;
  }

  javascriptGenerator.forBlock['arm_grab'] = function (block: { getFieldValue: (arg0: string) => any; }) {
    return '\n' + `Command.execute('./armMove -grab')`;
  }

  javascriptGenerator.forBlock['arm_put'] = function (block: { getFieldValue: (arg0: string) => any; }) {
    return '\n' + `Command.execute('./armMove -put')`;
  }

  const blocklyArea = document.getElementById('blocklyArea') as HTMLElement;
  const blocklyDiv = document.getElementById('blocklyDiv') as HTMLElement;
  blocklyWorkspace.value = Blockly.inject(blocklyDiv, {
    media: './node_modules/blockly/media/',
    // theme: Theme,
    toolbox: toolbox,
  });
  blocklyWorkspace.value.addChangeListener(updateCode);
  const onresize = () => {
    // Compute the absolute coordinates and dimensions of blocklyArea.
    let element = blocklyArea;
    let x = 0;
    let y = 0;
    do {
      x += element.offsetLeft;
      y += element.offsetTop;
      element = element.offsetParent as HTMLElement; // 确保类型安全
    } while (element);

    // Position blocklyDiv over blocklyArea.
    blocklyDiv.style.left = x + 'px';
    blocklyDiv.style.top = y + 'px';
    blocklyDiv.style.width = blocklyArea.offsetWidth + 'px';
    blocklyDiv.style.height = blocklyArea.offsetHeight + 'px';
    Blockly.svgResize(blocklyWorkspace.value);
    // console.log('resize');
  };
  window.addEventListener('resize', onresize, false);
  onresize();
})
</script>

<style scoped>
.home {
  --left-with: 55%;
  width: 100vw;
  display: flex;
  justify-content: center;
}

.left {
  width: var(--left-with);
  min-width: 700px;
  min-height: 100vh;
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  /* background-color: pink; */
}

.right {
  width: calc(100% - var(--left-with) - 5px);
  min-height: 100vh;
  display: flex;
  flex-direction: column-reverse;
  /* background-color: blue; */
}

.codeArea {
  background-color: grey;
  width: 100%;
  height: 50%;
}
</style>
